import { PrismaClient } from '@prisma/client'
import bcrypt from 'bcryptjs'
import { User, LoginRequest, RegisterRequest, AuthPayload } from '../types'

const prisma = new PrismaClient()

export class UserService {
  async authenticateUser(username: string, password: string): Promise<User | null> {
    const user = await prisma.user.findUnique({
      where: { username },
    })

    if (!user) {
      return null
    }

    const isPasswordValid = await bcrypt.compare(password, user.passwordHash)
    if (!isPasswordValid) {
      return null
    }

    return user
  }

  async createUser(userData: RegisterRequest): Promise<User> {
    const { username, password, email, phone, nickname } = userData
    
    // Hash password
    const passwordHash = await bcrypt.hash(password, 12)
    
    return prisma.user.create({
      data: {
        username,
        passwordHash,
        email,
        phone,
        nickname,
      },
    })
  }

  async getUserById(id: number): Promise<User> {
    const user = await prisma.user.findUnique({
      where: { id },
    })

    if (!user) {
      throw new Error('User not found')
    }

    return user
  }

  async getUserByUsername(username: string): Promise<User | null> {
    return prisma.user.findUnique({
      where: { username },
    })
  }

  async updateUser(id: number, updateData: Partial<User>): Promise<User> {
    const { password, ...data } = updateData
    
    // If password is being updated, hash it
    if (password) {
      data.passwordHash = await bcrypt.hash(password, 12)
    }
    
    return prisma.user.update({
      where: { id },
      data,
    })
  }

  async changePassword(id: number, currentPassword: string, newPassword: string): Promise<void> {
    const user = await prisma.user.findUnique({
      where: { id },
    })

    if (!user) {
      throw new Error('User not found')
    }

    const isCurrentPasswordValid = await bcrypt.compare(currentPassword, user.passwordHash)
    if (!isCurrentPasswordValid) {
      throw new Error('Current password is incorrect')
    }

    const newPasswordHash = await bcrypt.hash(newPassword, 12)
    
    await prisma.user.update({
      where: { id },
      data: { passwordHash: newPasswordHash },
    })
  }

  async deleteUser(id: number): Promise<void> {
    await prisma.user.delete({
      where: { id },
    })
  }

  async getAllUsers(page: number = 1, limit: number = 10) {
    const offset = (page - 1) * limit
    
    const [users, total] = await Promise.all([
      prisma.user.findMany({
        skip: offset,
        take: limit,
        select: {
          id: true,
          username: true,
          email: true,
          phone: true,
          nickname: true,
          avatar: true,
          role: true,
          createdAt: true,
          updatedAt: true,
        },
        orderBy: { createdAt: 'desc' },
      }),
      prisma.user.count(),
    ])

    return {
      data: users,
      pagination: {
        page,
        limit,
        total,
        pages: Math.ceil(total / limit),
      },
    }
  }
}